package com.darcye.clear.work;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.jdom2.Document;
import org.jdom2.Element;

import com.darcye.clear.reader.StyleFileReader;
import com.darcye.clear.reader.StyleFileReader.OnStyleFileReaderListener;
import com.darcye.clear.reader.entity.StyleEntity;
import com.darcye.clear.utils.DeleteLogger;
import com.darcye.clear.utils.FileList;

/**
 * 清理Style, 该清理器假设所有的style都包含在values文件夹下，并且文件名称包括styles。
 * @author Darcy
 * @date 2014-9-28 下午3:58:20
 * @version V1.0
 */
public class StyleWorker extends BaseWorker {
	
	private DeleteLogger logger = new DeleteLogger("Style");
	
	private Set<String> mScanStyleIds = new LinkedHashSet<String>();
	
	private Map<String, StyleEntity> mTotalStyleEntityMap = new LinkedHashMap<String, StyleEntity>();
	
	private Map<File,Document> mStyleDocuments = new HashMap<File,Document>();
	
	public StyleWorker(JavaWorker javaWorker,LayoutWorker layoutWorker,ManifestWorker manifestWorker){
		mScanStyleIds.addAll(javaWorker.getUsedStyleIdSet());
		mScanStyleIds.addAll(layoutWorker.getUsedStyleIdSet());
		mScanStyleIds.addAll(manifestWorker.getUsedStyleIdSet());
		mUsedStyleIdSet.addAll(mScanStyleIds);
	}
	
	public void execute() {
		recurseScanStyle();
		removeUnusedStyles();
		logger.finish();
	}
	
	/**
	 * 扫描所有styles文件
	 */
	private void recurseScanStyle(){
		StyleFileReader styleFileReader;
		FileList fl = new FileList(getResourcePath());
		List<File> styleFiles = fl.recurseListFiles(new FilenameFilter() {
			File pFile;
			public boolean accept(File dir, String name) {
				pFile = dir.getParentFile();
				return pFile.getName().startsWith("values")&&name.contains("styles");
			}
		});
		for (File styleFile : styleFiles) {
			styleFileReader = new StyleFileReader(styleFile);
			try {
				styleFileReader.setOnStyleFileReaderListener(new OnStyleFileReaderListener() {
					public void onComplete(Map<String, StyleEntity> styleEntityMap) {
						mTotalStyleEntityMap.putAll(styleEntityMap);
					}
				}).scan();
				mStyleDocuments.put(styleFile,styleFileReader.getDocument());
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		for (String styleName : mScanStyleIds) {
			recurseScanStyle1(styleName);
		}
	}
	
	/**
	 * 深度递归扫描Style属性
	 */
	private void recurseScanStyle1(String styleId){
		StyleEntity styleEntity = mTotalStyleEntityMap.get(styleId);
		mUsedAnimIdSet.addAll(styleEntity.getAnimIdSet());
		mUsedAnimatorIdSet.addAll(styleEntity.getAnimatorIdSet());
		mUsedTransitionIdSet.addAll(styleEntity.getTransitionIdSet());
		mUsedDrawableIdSet.addAll(styleEntity.getDrawableIdSet());
		mUsedColorIdSet.addAll(styleEntity.getColorIdSet());
		mUsedStringIdSet.addAll(styleEntity.getStringIdSet());
		mUsedIntegerIdSet.addAll(styleEntity.getIntegerIdSet());
		mUsedBoolIdSet.addAll(styleEntity.getBoolIdSet());
		mUsedDimenIdSet.addAll(styleEntity.getDimenIdSet());
		mUsedIdIdSet.addAll(styleEntity.getIdIdSet());
		String mParentStyleId = styleEntity.getParentStyleId();
		if( mParentStyleId != null &&!mUsedStyleIdSet.contains(mParentStyleId)){
			mUsedStyleIdSet.add(mParentStyleId);
			recurseScanStyle1(mParentStyleId);
		}
		if(!styleEntity.getChildrenStyleIds().isEmpty()){
			for (String childStyleId : styleEntity.getChildrenStyleIds()) {
				if(!mUsedStyleIdSet.contains(childStyleId)){
					mUsedStyleIdSet.add(childStyleId);
					recurseScanStyle1(childStyleId);
				}
			}
		}
	}
	
	/**
	 * 移除多余的Style
	 */
	private void removeUnusedStyles(){
		String styleName;
		Element rootEl;
		List<Element> styleEls;
		Document styleDoc;
		File styleFile;
		boolean isStyleFileChange ;
		for (Entry<File,Document> docEntry : mStyleDocuments.entrySet()) {
			isStyleFileChange = false;
			styleDoc = docEntry.getValue();
			styleFile = docEntry.getKey();
			rootEl = styleDoc.getRootElement();
			styleEls = new ArrayList<Element>();
			styleEls.addAll(rootEl.getChildren("style"));
			for (Element styleEl : styleEls) {
				styleName = styleEl.getAttribute("name").getValue();
				if(!mUsedStyleIdSet.contains(styleName)){
					logger.log(styleName, styleFile.getPath());
					rootEl.removeContent(styleEl);
					isStyleFileChange = true;
				}
			}
			if(isStyleFileChange && !isIgnoreDeleteFile(styleFile)){
				backupDelFile(styleFile);
				writeBack(styleFile, styleDoc);
			}
		}
	}
}
